﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace AutoupdateClient.Mgr
{
    internal class DownloadMgr
    {
        #region Instance

        private static DownloadMgr instance { set; get; } = null;

        public static DownloadMgr getInstance()
        {
            if (instance == null)
            {
                instance = new DownloadMgr();
            }

            return instance;
        }

        #endregion

        private AutoUpdate.Model.Model.fileTransfer.fs_version currentVersion { set; get; } = null;

        private Queue<AutoUpdate.Model.Model.fileTransfer.fs_inode> nodeQueue { set; get; } = new Queue<AutoUpdate.Model.Model.fileTransfer.fs_inode>();

        public AutoUpdate.Model.Model.fileTransfer.fs_inode currentNode { private set; get; } = null;

        public string workMode { set; get; } = "starting";//downloading // completed

        public string currrentFileName { set; get; } = string.Empty;

        public int downloadFileCount { private set; get; } = 0;

        public int downloadedFileIndex { private set; get; } = 0;

        public long currentFileLength { private set; get; } = 0;

        public int offset { private set; get; } = 0;
        public void getNewestVersion()
        {
            AutoUpdate.Model.Packet.RequestPacket request = new AutoUpdate.Model.Packet.RequestPacket();

            request.CommandText = "getNewestVersion";

            ActionMgr.getInstance().addAction(request.PacketID, new Action<AutoUpdate.Model.Packet.Packet>((AutoUpdate.Model.Packet.Packet packet) =>
          {
              this.currentVersion = AutoUpdate.Utility.Helper.JsonHelper.getObject<AutoUpdate.Model.Model.fileTransfer.fs_version>(packet.MessageContent);

              if (this.currentVersion != null)
              {
                  if (this.currentVersion.files != null)
                  {
                      if (this.currentVersion.files.Count > 0)
                      {
                          this.nodeQueue.Clear();


                          string executePath = ConfigMgr.getInstance().config.executePath;

                          if (executePath.EndsWith("\\"))
                          {
                              executePath = executePath.Substring(0, executePath.Length - 1);
                          }

                          Console.WriteLine(executePath);




                          foreach (var item in this.currentVersion.files)
                          {
                              string fileName = executePath + item.relativePath;

                              if (File.Exists(fileName))
                              {
                                  string md5 = AutoUpdate.Utility.Helper.FileHelper.fileMd5(fileName);

                                  if (md5 != item.md5)
                                  {
                                      this.nodeQueue.Enqueue(item);
                                  }
                              }
                              else
                              {
                                  this.nodeQueue.Enqueue(item);
                              }
                          }

                          if (this.nodeQueue.Count == 0)
                          {
                              this.workMode = "completed";

                              this.executeFile();

                              return;
                          }


                          this.downloadFileCount = this.nodeQueue.Count;

                          this.currentNode = this.nodeQueue.Dequeue();

                          this.currrentFileName = this.currentNode.name;

                          this.offset = 0;

                          this.currentFileLength = this.currentNode.length;

                          this.workMode = "downloading";

                          this.downloadFile();
                      }
                  }
              }
          }));

            ClientMgr.getInstance().client.sendMessage(AutoUpdate.Utility.Helper.JsonHelper.getString(request));
        }

        private void executeFile()
        {

        }

        private void downloadFile()
        {
            if (this.currentNode == null)
            {
                return;
            }

            string executePath = ConfigMgr.getInstance().config.executePath;

            if (executePath.EndsWith("\\"))
            {
                executePath = executePath.Substring(0, executePath.Length - 1);
            }

            Console.WriteLine(executePath);

            string fileName = executePath + this.currentNode.relativePath;

            string filePath = fileName.Replace(this.currentNode.name, "");

            if (this.offset == 0)
            {
                if (File.Exists(fileName))
                {
                    File.Delete(fileName);
                }
            }

            if (filePath.EndsWith("\\"))
            {
                filePath = filePath.Substring(0, filePath.Length - 1);
            }

            if (!Directory.Exists(filePath))
            {
                Directory.CreateDirectory(filePath);
            }





            AutoUpdate.Model.Model.fileTransfer.fs_inodeContent nodeModel = new AutoUpdate.Model.Model.fileTransfer.fs_inodeContent();

            nodeModel.md5 = this.currentNode.md5;

            nodeModel.version = this.currentVersion.version;

            nodeModel.offset = this.offset;

            AutoUpdate.Model.Packet.RequestPacket request = new AutoUpdate.Model.Packet.RequestPacket();

            request.CommandText = "downloadFile";

            request.MessageContent = AutoUpdate.Utility.Helper.JsonHelper.getString(nodeModel);


            ActionMgr.getInstance().addAction(request.PacketID, new Action<AutoUpdate.Model.Packet.Packet>((AutoUpdate.Model.Packet.Packet packet) =>
        {

            AutoUpdate.Model.Model.fileTransfer.fs_inodeContent inodeModel = AutoUpdate.Utility.Helper.JsonHelper.getObject<AutoUpdate.Model.Model.fileTransfer.fs_inodeContent>(packet.MessageContent);

            if (inodeModel != null)
            {
                AutoUpdate.Utility.Helper.FileHelper.fileWrite(fileName, this.offset, inodeModel.length, inodeModel.contents);


                if (this.offset + inodeModel.length == this.currentNode.length)
                {
                    this.offset = 0;

                    this.downloadedFileIndex++;

                    if (this.nodeQueue.Count > 0)
                    {
                        this.currentNode = this.nodeQueue.Dequeue();

                        this.currentFileLength = this.currentNode.length;

                        this.currrentFileName = this.currentNode.name;

                        this.downloadFile();
                    }
                    else
                    {
                        this.currentNode = null;

                        this.workMode = "completed";

                        this.executeFile();
                    }
                }
                else
                {
                    this.offset = this.offset + inodeModel.length;

                    this.downloadFile();
                }
            }
        }));

            ClientMgr.getInstance().client.sendMessage(AutoUpdate.Utility.Helper.JsonHelper.getString(request));
        }
    }
}
